package enjoyhiking.service;

import java.util.Calendar;


import enjoyhiking.context.EnjoyHikingConfig;
import enjoyhiking.util.SdCard;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.os.Vibrator;
import android.util.Log;

interface EnjoyHikingListener
{
	void onActive( String msg );
}

public class EnjoyHikingService extends Service implements EnjoyHikingListener
{

	/**
	 * debug tag
	 */
	public static final String 		DEBUG_TAG = "HikingService";
	
	/**
	 * the minimum time interval for notifications, in milliseconds
	 */
	public static final int			GPS_INTERVAL_TIME 	= 60000;
	
	/**
	 * the minimum distance interval for notifications, in meters
	 */
	public static final int			GPS_MINIMUM_DISTANCE = 0;
	
	/**
	 * Location Service
	 */
	private LocationListener 		mLocationListener 	= null;
	private LocationManager 		mLocationManager 	= null;
	
	private EnjoyHikingConfig		mConfig				= null;
	
	/**
	 * sensors
	 */
	SensorManager 					mSensorManager 		= null;
	Vibrator 						mVibrator 			= null;
	Accelerometer 					mAcclerometer 		= new Accelerometer(); 
	Orientation 					mOrientation 		= new Orientation();
	MagneticField 					mMagneticField 		= new MagneticField();
	
	/**
	 * binder
	 */
	IBinder mBinder = new EnjoyHikingServiceBinder();
	
	/**
	 * file control for SD card
	 */
	SdCard 							mSdCard 			= null;
	
	/**
	 * 
	 */
	boolean 						mIsSensorLogging	= false;
	
	@Override
	public void onCreate() 
	{
		Log.i(DEBUG_TAG, "onCreate()");

		super.onCreate();
	}
	
	public void setConfig(EnjoyHikingConfig config)
	{
		mConfig = config;
		
		initSensors();
		
		Calendar cal = Calendar.getInstance();
		
		String dateString = String.format("%04d-%02d-%02d", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH));
		String timeString = String.format("%02d:%02d:%02d", cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND));
		
		timeString = timeString.replace(':', ';');
		
		String state = Environment.getExternalStorageState();
		
		if(!state.equals(Environment.MEDIA_MOUNTED))
		{
			Log.e(DEBUG_TAG, "Media doesn't read and write");
		}
		else
		{
			Log.e(DEBUG_TAG, "Media is good to read and write");
		}
		
		mSdCard = new SdCard(mConfig.getUserName(), dateString, timeString, mConfig.getActivityType().toString() );
		mSdCard.append("---START---");
		mSdCard.append("\r\n");
		
	}
	
	@Override
	public void onStart(Intent intent, int startId) 
	{
		Log.i(DEBUG_TAG, "onStart()");
		
		super.onStart(intent, startId);
	}
	
	@Override
	public IBinder onBind(Intent intent) 
	{
		Log.i(DEBUG_TAG, "onBind()");
		
		return mBinder;
	}
	
	@Override
	public void onRebind(Intent intent) 
	{
		Log.i(DEBUG_TAG, "onRebind()");
		
		super.onRebind(intent);
	}
	
	@Override
	public boolean onUnbind(Intent intent) 
	{
		Log.i(DEBUG_TAG, "onUnbind()");
		
		return super.onUnbind(intent);
	}
	
	@Override
	public void onDestroy() 
	{
		Log.i(DEBUG_TAG, "onDestroy()");

		if(mSensorManager != null)
		{
			if(mConfig.isLocationEnabled() == true)
			{
				mLocationManager.removeUpdates( mLocationListener );
			}
			if(mConfig.isAccelerometerEnabled() == true)
			{
				mSensorManager.unregisterListener(mAcclerometer);
			}
			if(mConfig.isOrientationEnabled() == true)
			{
				mSensorManager.unregisterListener(mOrientation);
			}
			if(mConfig.isMagneticFieldEnabled() == true)
			{
				mSensorManager.unregisterListener(mMagneticField);
			}
		}

		super.onDestroy();
	}

	@Override
	public void onActive(String msg) 
	{
	}
	
	public int convertLocToInt( double location )
	{
		int CovertNum = (int)( location * (1000000) );

		return CovertNum;
	}
	
	public void close()
	{
		stopSensorLogging();
		
		if(mSdCard != null)
		{
			mSdCard.append("---END---");
			mSdCard.close();
		}
	}
	
	public void stopSensorLogging()
	{
		mIsSensorLogging = false;
	}
	
	public void startSensorLogging()
	{
		mIsSensorLogging  = true;
	}
	
	private void initSensors() 
	{
		mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
		mLocationManager = (LocationManager) getSystemService( Context.LOCATION_SERVICE);
		mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
		
		for (Sensor sensor : mSensorManager.getSensorList(Sensor.TYPE_ALL)) 
		{
			Log.d(DEBUG_TAG, String.format("SENSOR_TYPE: %d, SENSOR_NAME : %s", sensor.getType(), sensor.getName()));
		}
		
		if( mConfig.isLocationEnabled() == true)
		{
			mLocationListener = new EnjoyHikingLocationListener();
			mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_INTERVAL_TIME, GPS_MINIMUM_DISTANCE, mLocationListener);
		}

		if( mConfig.isAccelerometerEnabled() == true)
			mSensorManager.registerListener(mAcclerometer, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
		
		if( mConfig.isOrientationEnabled() == true)
			mSensorManager.registerListener(mOrientation, mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), SensorManager.SENSOR_DELAY_NORMAL);
		
		if(mConfig.isMagneticFieldEnabled() == true)
			mSensorManager.registerListener(mMagneticField, mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_NORMAL);
		
		startSensorLogging();
	}
	
	class EnjoyHikingLocationListener implements LocationListener
	{
		@Override
		public void onLocationChanged(Location location) 
		{
			Log.d(DEBUG_TAG, "Latitude="+convertLocToInt(location.getLatitude()) +" Longitude=" + convertLocToInt( location.getLongitude()));
		}

		@Override
		public void onProviderDisabled(String provider) 
		{
			Log.i(DEBUG_TAG, "GPS is now disabled" );
		}

		@Override
		public void onProviderEnabled(String provider) 
		{
			Log.i(DEBUG_TAG, "GPS is now enabled" );
		}

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) 
		{
		}
	}
	
	class Accelerometer implements SensorEventListener
	{
		@Override
		public void onAccuracyChanged(Sensor sensor, int accuracy) 
		{
			//Log.i(DEBUG_TAG, String.format("resolution: %f, accuracy: %d", sensor.getResolution(), accuracy));
		}

		@Override
		public void onSensorChanged(SensorEvent event) 
		{
			if(mIsSensorLogging == true)
			{
				Log.d(DEBUG_TAG, "Logging...");
				
				Calendar mCalendar = Calendar.getInstance();
				
				String dateString = String.format("(%04d-%02d-%02d)", mCalendar.get(Calendar.YEAR), mCalendar.get(Calendar.MONTH) + 1, mCalendar.get(Calendar.DAY_OF_MONTH));
				String timeString = String.format(" (%02d:%02d:%02d)", mCalendar.get(Calendar.HOUR_OF_DAY), mCalendar.get(Calendar.MINUTE), mCalendar.get(Calendar.SECOND));
				//String result = String.format("Time: %s, Accelerometer: X: %f, Y: %f, Z: %f", dateString + timeString, event.values[0], event.values[1], event.values[2]);
				
				mSdCard.append(String.format("Time: %s, Accelerometer: X: %f, Y: %f, Z: %f", dateString + timeString, event.values[0], event.values[1], event.values[2]));
				mSdCard.append("\r\n");
			}
		}
	} 
	
	class Orientation implements SensorEventListener
	{
		@Override
		public void onAccuracyChanged(Sensor sensor, int accuracy) 
		{
		}

		@Override
		public void onSensorChanged(SensorEvent event) 
		{
			if(mIsSensorLogging == true)
			{
				//Log.i(EnjoyHikingService.DEBUG_TAG, String.format("Orientation: X: %f, Y: %f, Z: %f ", event.values[0], event.values[1], event.values[2]));	
			}
		}
		
	}
	
	class MagneticField implements SensorEventListener
	{
		@Override
		public void onAccuracyChanged(Sensor sensor, int accuracy) 
		{
		}

		@Override
		public void onSensorChanged(SensorEvent event) 
		{
			if(mIsSensorLogging == true)
			{
				//Log.i(EnjoyHikingService.DEBUG_TAG, String.format("MagneticField: %f, %f, %f", event.values[0], event.values[1], event.values[2]));				
			}

		}
		
	}
	
	public class EnjoyHikingServiceBinder extends Binder
	{
		public EnjoyHikingService getService()
		{
			return EnjoyHikingService.this;
		}
	}
}
